import java.lang.reflect.Method;
import java.lang.reflect.Field;
import java.lang.reflect.Constructor;

public class ValidateUserAccount {
    static Class UserAccountClass = null;
    
    public ValidateUserAccount() {
        
    }
    
    static void printFieldInformation(UserAccount obj) {
        Field [] fields = obj.getClass().getFields();
        if(fields == null) {
            System.out.print("The class have no public field");
        } else {
            System.out.print("Public fields of the class");
            for(Field x : fields) {
                System.out.print(x);
            }
        }
    }
    
    static void printMethodInformation(UserAccount obj) {
        Method [] methods = obj.getClass().getMethods();
        if(methods == null) {
            System.out.print("The class have no public method");
        } else {
            System.out.print("Public methods of the class");
            for(Method x : methods) {
                System.out.print(x);
            }
        }
    }
    
    static Object createObject(Constructor constructor, Object[] arguments) {
        Object object = null;
        try {
            object = constructor.newInstance(arguments);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return object;
    }
    
    static Object createObject(Object[] arguments) {
        Object object = null;
        Class [] argTypes = null;
        if(arguments != null) {
            argTypes = new Class[arguments.length];
            for(int i = 0; i < arguments.length; i++) {
                argTypes[i] = arguments[i].getClass();
                if(argTypes[i].getName().equals("java.lang.Integer")) {
                    argTypes[i] = int.class;
                }
                if(argTypes[i].getName().equals("java.lang.Double")) {
                    argTypes[i] = double.class;
                }
            }
        }
        try {
            Constructor constructor = UserAccountClass.getConstructor(argTypes);
            object = constructor.newInstance(arguments);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return object;
    }
    
    static void setFieldValues(UserAccount obj, String fieldName, Object value) {
        try {
            Field [] fields = obj.getClass().getFields();
            for(Field field : fields) {
                if(field.getName().equals(fieldName)) {
                    setFieldValues(obj, fieldName, value);
                    return;
                }
            }
            Method [] methods = obj.getClass().getMethods();
            for(Method method : methods) {
                if(method.getName().equalsIgnoreCase("set" + fieldName)) {
                    method.invoke(obj, value);
                    return;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    static Object getFieldValue(UserAccount obj, String fieldName) {
        Field [] fields = obj.getClass().getFields();
        try {
            for(Field field : fields) {
                if(field.getName().equals(fieldName)) {
                    return field.get(obj);
                }
            }
            Method [] methods = obj.getClass().getMethods();
            for(Method method : methods) {
                if(method.getName().equalsIgnoreCase("get"+fieldName)) {
                        return method.invoke(obj);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    
    public static void main(String[] args) {
        try {
            UserAccountClass = Class.forName("UserAccount");
            System.out.println("Creating dynamically an UserAccount object:");
            Class [] paramTypes = new Class []{int.class,
                String.class,
                String.class,
                double.class,
                String.class};
            
            Object [] parameters = new Object []{1, "Tran Quoc", "Ninh", 999.999, "tqninh"};
            Constructor constructor = UserAccountClass.getConstructor(paramTypes);
            UserAccount userAccount1 = (UserAccount)createObject(constructor, parameters);
            userAccount1.output();
            
            parameters = new Object [] {(int)2,"Nguyen Thi","Ngoan",(double)888.888,"sweetyuuri"};
            UserAccount userAccount2 = (UserAccount)createObject(parameters);
            userAccount2.output();
            
            UserAccount userAccount3 = (UserAccount)createObject(null);
            userAccount3.output();
            setFieldValues(userAccount3,"accountNumber",10);
            setFieldValues(userAccount3,"firstName","It");
            setFieldValues(userAccount3,"lastName","mine");
            setFieldValues(userAccount3,"accountBalance",1000.000);
            setFieldValues(userAccount3,"password","me1986");
            userAccount3.output();
            System.out.print(getFieldValue(userAccount3,"accountBalance"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}